using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using Microsoft.Exchange.WebServices.Data;
using Orbitone.MeetingRooms.Services.Model;

namespace Orbitone.MeetingRooms.Services
{
    public class ExchangeService : IExchangeService
    {
        private readonly Microsoft.Exchange.WebServices.Data.ExchangeService m_service;

        public ExchangeService()
        {
            var username = ConfigurationManager.AppSettings["username"];
            var password = ConfigurationManager.AppSettings["password"];
            var domain = ConfigurationManager.AppSettings["domain"];

            // Connect to Exchange Web Services as user1 at contoso.com.
            m_service = new Microsoft.Exchange.WebServices.Data.ExchangeService(ExchangeVersion.Exchange2010_SP1);
            m_service.Credentials = new WebCredentials(username, password, domain);
            m_service.AutodiscoverUrl(ConfigurationManager.AppSettings["autodiscovery_email"]);
        }

        #region Implementation of IExchangeService

        //TODO verwijderen enddate
        public List<AvailabilityModel> GetAvailability(List<MailboxModel> mailboxes, DateTime startDate, DateTime endDate, int interval)
        {
            var attendees = mailboxes.Select(m => new AttendeeInfo(m.EmailAddress)).ToList();

            // Specify availability options.
            var myOptions = new AvailabilityOptions
            {
                RequestedFreeBusyView = FreeBusyViewType.DetailedMerged,
                MergedFreeBusyInterval = interval,
            };

            var freeBusyResults = m_service.GetUserAvailability(attendees,
                                                                new TimeWindow(startDate, startDate.AddDays(1)),
                                                                    AvailabilityData.FreeBusy,
                                                                    myOptions);

            var availabilityList = new List<AvailabilityModel>();

            for (int mbNumCount = 0; mbNumCount < mailboxes.Count; mbNumCount++)
            {
                var mailbox = mailboxes[mbNumCount];
                var available = freeBusyResults.AttendeesAvailability[mbNumCount];

                var calEvents = new List<CalendarEventModel>();
                if (available.CalendarEvents != null)
                {
                    foreach (var calendarEvent in available.CalendarEvents)
                    {
                        var id = calendarEvent.Details.StoreId;
                        var originalId = new AlternateId(IdFormat.HexEntryId, id, mailbox.EmailAddress);
                        var newId = m_service.ConvertId(originalId, IdFormat.EwsId) as AlternateId;

                        if (newId != null)
                        {
                            var fetch = GetAppointment(newId.UniqueId, mailbox.EmailAddress, calendarEvent.StartTime, calendarEvent.EndTime);

                            var calEvent = new CalendarEventModel()
                                               {
                                                   Id = newId.UniqueId,
                                                   Mailbox = mailbox.EmailAddress,
                                                   EndDate = fetch.EndDate,
                                                   StartDate = fetch.StartDate,
                                                   Subject = fetch.Subject,
                                                   UserId = fetch.UserId,
                                                   UserName = fetch.UserName
                                               };
                            calEvents.Add(calEvent);
                        }
                    }
                }
                availabilityList.Add(new AvailabilityModel() { Mailbox = mailbox, CalendarEvents = calEvents });
            }

           return availabilityList;
        }

        public string SaveAppointment(CalendarEventModel appointmentModel)
        {
            var folderId = new FolderId(WellKnownFolderName.Calendar, appointmentModel.Mailbox);

            var appointment = new Appointment(m_service)
            {
                Subject = appointmentModel.Subject,
                Start = appointmentModel.StartDate.ToUniversalTime(),
                End = appointmentModel.EndDate.ToUniversalTime()
            };

            var mapiGuid = new Guid("{00062002-0000-0000-C000-000000000046}");
            var propertyDefinition = new ExtendedPropertyDefinition(mapiGuid, "UserId", MapiPropertyType.String);
            appointment.SetExtendedProperty(propertyDefinition, appointmentModel.UserId + ";" + appointmentModel.UserName);

            appointment.Save(folderId, SendInvitationsMode.SendOnlyToAll);

            return appointment.Id.UniqueId;
        }

        public void DeleteAppointment(string calendarEventId, string roomEmail)
        {
            var appointment = Appointment.Bind(m_service, calendarEventId);
            appointment.Delete(DeleteMode.MoveToDeletedItems);
        }

        public List<AppointmentModel> FindAppointments(string filterValue, string mailbox)
        {
            throw new NotImplementedException();
        }

        public AppointmentModel GetAppointment(string alternativeIdType, string mailbox, DateTime startTime, DateTime endTime)
        {
            var mapiGuid = new Guid("{00062002-0000-0000-C000-000000000046}");
            var propertyDefinition = new ExtendedPropertyDefinition(mapiGuid, "UserId", MapiPropertyType.String);
            var propertySet = new PropertySet(BasePropertySet.FirstClassProperties, ItemSchema.Subject, propertyDefinition);

            var appointment = Appointment.Bind(m_service, alternativeIdType, propertySet);

            var extProp = appointment.ExtendedProperties.Where(p => p.PropertyDefinition.Name.Equals("UserId")).FirstOrDefault();
            var userId = extProp != null ? extProp.Value.ToString() : string.Empty;

            var user = userId.Split(';');

            var userName = string.Empty;
            if (user.Count() > 1)
            {
                userId = user[0];
                userName = user[1];
            }

            var startDate = new DateTime(
                startTime.ToLocalTime().Year,
                startTime.ToLocalTime().Month,
                startTime.ToLocalTime().Day, 
                appointment.Start.ToLocalTime().Hour, 
                appointment.Start.ToLocalTime().Minute, 
                appointment.Start.ToLocalTime().Second);
            
            var endDate = new DateTime(
                endTime.ToLocalTime().Year,
                endTime.ToLocalTime().Month,
                endTime.ToLocalTime().Day, 
                appointment.End.ToLocalTime().Hour, 
                appointment.End.ToLocalTime().Minute, 
                appointment.End.ToLocalTime().Second);

            var appointmentModel = new AppointmentModel()
            {
                Id = appointment.Id.UniqueId,
                StartDate = startDate,
                EndDate = endDate,
                Mailbox = mailbox,
                Subject = appointment.Subject,
                UserId = userId,
                UserName = userName,
            };

            return appointmentModel;
        }

        #endregion
    }
}